﻿using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

namespace MassiveBattle.Controller
{
	public class MemberController : BaseController
	{
		private GameObject positionObject;

		public override Vector3 Position { get; protected set; }

		protected override bool IsCanAction
		{
			get
			{
				if (!Manager.IsAttackTypeValid(Stat.atkType.Get(Manager.Monitor)))
					return false;

				if (Manager.TacticsType == ETactics.ATTACK && IsSidePlayer)
					return true;

				return IsCaster || IsHealer || Line == ELine.FIRST;
			}
		}
		public override bool IsHealer { get; protected set; }

		public void Init(MemberModel data, ESide side, ELine line, int pos, EArea area)
		{
			Name = data.name;

			Stat = MemberStat.Create(data.CalcUnitStat(), Manager.Monitor);

			Init(data.model, side, line, pos, area);
			InitSkill(data);

			HealthPointCur = Stat.baseHP.Get(Manager.Monitor);

			FsmMain.Transit(EStateMain.idle);

			IsAlive = true;
		}

		protected override void InitClass()
		{
			base.InitClass();

			//데미지 폰트 미리 생성//
			if (damageFont == null)
				damageFont = ModelGameObject.AddComponent<DamageFont>();

			for (int i = 0; i < 3; i++)
			{
				damageFont.ShowDamage(true, false, pointEffectFont, 1, this, null, 0);
			}
			damageFont.ShowDamage(false, false, pointEffectFont, 1, this, null, 1);
			damageFont.DeleteAllDamageFont();
		}

		protected override void InitTake()
		{
			string takePath = "MassBattle/" + ClassName.ToString() + (string.IsNullOrEmpty(Gender) ? "" : "_" + Gender) + "/";
			var takeIdList = Utility.GetEnumValues(EMassTake.down01, EMassTake.damage01, EMassTake.idle02, EMassTake.Max);

			foreach (var takeType in takeIdList)
			{
				var take = Manager.TakePool[takePath + takeType];

				if (take == null)
					continue;

				takeDic.Add(takeType.ToString(), take);
			}
		}

		protected override void InitFsm()
		{
			FsmMain = new Fsm<EStateMain>();
			FsmMain.AddTransition(EStateMain.idle, EStateMain.forward, EStateMain.die);

			var state = FsmMain.AddState(EStateMain.idle);
			state.AddTransition(EStateMain.attack, EStateMain.heal, EStateMain.skill);
			state.EventStart = OnIdleStateStart;

			state = FsmMain.AddState(EStateMain.forward);
			state.AddTransition(EStateMain.idle);
			state.EventStart = OnForwardStateStart;
			state.EventTakeEnd = OnIdleStateTakeEnd;

			state = FsmMain.AddState(EStateMain.die);
			state.EventStart = OnDieStateStart;
			state.EventTakeEnd = OnDieStateTakeEnd;

			state = FsmMain.AddState(EStateMain.attack);
			state.AddTransition(EStateMain.idle);
			state.EventStart = OnAttackStateStart;
			state.EventTakeEnd = OnIdleStateTakeEnd;

			state = FsmMain.AddState(EStateMain.heal);
			state.AddTransition(EStateMain.idle);
			state.EventStart = OnHealStateStart;
			state.EventTakeEnd = OnIdleStateTakeEnd;

			state = FsmMain.AddState(EStateMain.skill);
			state.AddTransition(EStateMain.idle);
			state.EventStart = OnSkillStateStart;
			state.EventTakeEnd = OnIdleStateTakeEnd;
		}

		private void InitSkill(MemberModel data)
		{
			var skillList = data.GetSkills();

			SkillData = skillList.Length <= 0 ? null : skillList[0];
		}

		protected override void OnDestroy()
		{
			base.OnDestroy();

			if (positionObject != null)
				Destroy(positionObject);
		}

		protected override void OnDie()
		{
			Manager.UI.CountPlayer = Manager.DataList[ESide.PLAYER].CharacterList.Count(data => data.IsAlive);
			Manager.UI.ShowUnitDieNotiEffect(this);

			FsmMain.Transit(EStateMain.die);
		}

		protected override void EndOfPlay(IEventlinePlayer param)
		{
			base.EndOfPlay(param);

			if (Manager.IsRaid)
				ModelTransform.rotation = IsSidePlayer ? Quaternion.Euler(0, 180, 0) : Quaternion.Euler(0, 0, 0);
			else
				ModelTransform.rotation = IsSidePlayer ? Quaternion.Euler(0, 90, 0) : Quaternion.Euler(0, -90, 0);
		}

		protected void OnIdleStateStart()
		{
			PlayTake(EMassTake.idle01, new[] { ModelGameObject }, true);
		}

		protected void OnIdleStateTakeEnd()
		{
			FsmMain.Transit(EStateMain.idle);
		}

		protected void OnDieStateStart()
		{
			PlayTake(EMassTake.die01, new[] { ModelGameObject });
		}

		protected void OnDieStateTakeEnd()
		{
			Manager.RemoveMember(this);

			ModelGameObject.SetActive(false);
		}

		protected void OnAttackStateStart()
		{
			if (!SetTarget(GetCandidate().GetWhere(data => data.Line == ELine.FIRST).GetTake(1, Query.ECount.TAUNT)))
				return;

			SetDamagePoint(SetDamagePoint_Attack_A);

			if (!Vector3.Equals(Target.ModelTransform.position, ModelTransform.position))
				ModelTransform.rotation = Quaternion.LookRotation(Target.ModelTransform.position - ModelTransform.position);

			PlayTake_Attack_Source_Target();
		}

		protected void OnHealStateStart()
		{
			SetTarget(new List<BaseController> { Manager.GetHealTarget(Side) });

			if (!IsTargetExist)
				return;

			PlayTake(EMassTake.skill01, new[] { ModelGameObject, Target.ModelGameObject, EventlineStaticActor.Camera });
		}

		protected void OnSkillStateStart()
		{
			if (!SetTarget(Manager.GetSkillTarget(this)))
				return;

			SetDamagePoint(SetDamagePoint_Skill_A);

			PlayTake_Skill_Source_Target_Camera();

			AttachCamera_Skill_A();
		}

		protected void OnForwardStateStart()
		{
			positionObject = positionObject ?? new GameObject("PositionObject");
			positionObject.transform.position = Position;

			PlayTake(EMassTake.forward01, new[] { ModelGameObject, positionObject });

			if (!Vector3.Equals(Position, ModelTransform.position))
				ModelTransform.rotation = Quaternion.LookRotation(Position - ModelTransform.position);

			ActionTimeLeft += 2f;
		}
	}
}
